
/**
 * AppleIIGo
 * Floppy Disk Image class
 * (C) 2008 by Marc S. Ressl (mressl@umich.edu)
 * Released under the GPL
 */

#include <stdio.h>
#include "Motherboard.h"

#ifndef FLOPPYDISKIMAGE_H
#define FLOPPYDISKIMAGE_H

#define Q3_CLOCKRATE			(1020484 * 2)

typedef enum {
	FLOPPYDISKTYPE_5_25,
	FLOPPYDISKTYPE_3_5,
};

#define DISK_5_25_TRACKNUM		(40 * 4)
#define DISK_5_25_HEADNUM		1
#define DISK_5_25_MOTORRPM		300
#define DISK_5_25_DATARATE		(Q3_CLOCKRATE / 8)
#define DISK_5_25_TRACK_BITNUM	(DISK_5_25_DATARATE * 60 / DISK_5_25_MOTORRPM)
#define DISK_3_5_TRACKNUM		80
#define DISK_3_5_HEADNUM		2
#define DISK_3_5_MOTORRPM_1		401.9241
#define DISK_3_5_MOTORRPM_2		438.4626
#define DISK_3_5_MOTORRPM_3		482.3089
#define DISK_3_5_MOTORRPM_4		535.8988
#define DISK_3_5_MOTORRPM_5		602.8861
#define DISK_3_5_DATARATE		(Q3_CLOCKRATE / 4)

class FloppyDiskImage {
public:
	static class FloppyDiskImage * getInstance(UINT32 diskType,
											   char * diskImagePath);
	
	FloppyDiskImage(UINT32 diskType, char * floppyDiskImage);
	virtual ~FloppyDiskImage();
	
	UINT32 getDiskType();
	UINT32 getTrackNum();
	void setTrackIndex(UINT32 value);
	UINT32 getTrackIndex();
	UINT32 getHeadNum();
	void setHeadIndex(UINT32 value);
	UINT32 getHeadIndex();
	
	void getTrackData(UINT8 ** data, UINT32 * bitNum, UINT32 * bitIndex);
	UINT8 readNibble();
	UINT8 readNibble(UINT32 * bitNum);
	void writeNibble(UINT8 value);
	void writeNibble(UINT8 value, UINT32 bitNum);
	UINT32 getNibbleNum();
	
	void setWriteProtected(bool isWriteProtected);
	bool isWriteProtected();
	bool isWriteEnabled();
	void setModified();
	bool isModified();

	char * getDiskImagePath();
	
protected:
	FILE * diskImageFile;
	
	bool isDiskImageOpened();
	
	void setTrackBitNum(UINT32 bitNum);
	bool allocateDisk();
	
private:
	char * diskImagePath;
	
	UINT32 diskType;
	UINT32 diskTrackIndex;
	UINT32 diskTrackNum;
	UINT32 diskHeadIndex;
	UINT32 diskHeadNum;
	UINT32 * diskTrackBitNum;
	UINT32 * diskTrackOffset;
	UINT8 * diskData;
	
	UINT8 emptyDiskData;
	
	UINT32 trackBitNum;
	UINT8 * trackData;
	UINT32 trackBitIndex;
	
	bool isWriteProtectedValue;
	bool isWriteEnabledValue;
	bool isModifiedValue;
	
	UINT32 getTrackBitNum(UINT32 trackIndex, UINT32 diskType);
	void updateTrack();
};

#endif
